﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Shapes.Geometry;

namespace ShapesExtensions
{
    /// <summary>
    /// This class represents a 2D-Camera. pass the GetCameraMatrix() method to SpriteBatch.Begin()
    /// </summary>
    public class Camera2D : ITransformable2D
    {

        public Vector2 Position { get { return Transform.Position; } set { Transform.Position = value; } }

        public Vector2 Origin { get { return Transform.Origin; } set { Transform.Origin = value; } }

        public Vector2 Scale { get { return Transform.Scale; } set { Transform.Scale = value; } }

        public Angle Rotation { get { return Transform.Rotation; } set { Transform.Rotation = value; } }

        /// <summary>
        /// The transformation of the Camera. Note that you move the camera, not the world.
        /// </summary>
        public Transformation2D Transform { get; private set; }

        /// <summary>
        /// The Rectangle which covers the area the user can see. 
        /// Use it for intersection tests if you want.
        /// </summary>
        public Rect CameraRect { get; private set; }

        /// <summary>
        /// Creates a new instance.
        /// </summary>
        /// <param name="graphics">need to read the screen size</param>
        public Camera2D(GraphicsDevice graphics)
        {
            // create the CameraRect, which is as big as the screen
            CameraRect = new Rect(
                graphics.PresentationParameters.BackBufferWidth,
                graphics.PresentationParameters.BackBufferHeight
                );

            // set the Camera Transform to the Rect's Transform: when one of them change, the other do too
            Transform = CameraRect.Transform;

            // center the origin
            Transform.Origin = new Vector2(
                0.5f * graphics.PresentationParameters.BackBufferWidth,
                0.5f * graphics.PresentationParameters.BackBufferHeight);
        }

        /// <summary>
        /// Gets the Matrix for the Camera (which is the inverted transform)
        /// </summary>
        /// <returns>the camera matrix</returns>
        public Matrix GetCameraMatrix()
        {
            return
                      Matrix.CreateTranslation(-Transform.Origin.X, -Transform.Origin.Y, 0)
                    * Matrix.CreateScale(1 / Transform.Scale.X, 1 / Transform.Scale.Y, 1)
                    * Matrix.CreateRotationZ(Transform.Rotation.ClockwiseRadians)
                    * Matrix.CreateTranslation(-Transform.Position.X, -Transform.Position.Y, 0);
        }
    }
}
